package com.ruoyi.project.module.response.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.ruoyi.project.module.response.domain.Response;
import com.ruoyi.project.module.response.domain.ResponseCompletion;
import com.ruoyi.project.module.response.domain.ResponseFiliation;
import com.ruoyi.project.module.response.domain.ResponseParam;
import com.ruoyi.project.module.response.mapper.ResponseParamMapper;
import org.shoukaiseki.apiview.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;

/**
 * com.ruoyi.project.module.response.service.ResponseParamServiceImpl <br>
 * @ClassName ResponseParamServiceImpl
 * @Description TODO: 接口返回值业务接口
 * @Author Rick
 * @Date 2018/10/15 10:36
 * @Vesion 1.0.0
 */
@Service
public class ResponseParamServiceImpl implements IResponseParamService {

    public final static Logger logger= LoggerFactory.getLogger(ResponseParamServiceImpl.class);

    @Resource
    private ResponseParamMapper responseParamMapper;

    public static final int RESPONSE_VALUE_TYPE_STRING=0;
    public static final int RESPONSE_VALUE_TYPE_NUMBER=1;
    public static final int RESPONSE_VALUE_TYPE_ARRAY=2;
    public static final int RESPONSE_VALUE_TYPE_OBJECT=3;

    @Override
    public List<ResponseParam> getList(Long apiProjectId) {
        return responseParamMapper.getList(apiProjectId);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int addResponseParam(String json,Long projectId,boolean ignorePageInfo) {
        JSONObject jsonObject = null;
        if(null != json){
            json = json.trim().replaceAll("\t","").replaceAll("\n","").replaceAll("\r","");
            jsonObject = JSONObject.parseObject(json);
        }
        List<ResponseParam> list =  Lists.newLinkedList();
        analysisParam(ignorePageInfo,jsonObject,null,list,null);
        if(list.isEmpty()){
            return 0;
        }
        List<ResponseFiliation> filiationList = Lists.newLinkedList();
        List<Response> responseList = Lists.newLinkedList();
        for (int i = 0; i < list.size(); i++) {
            if(null != list.get(i).getParentResponseCode()){
                ResponseFiliation responseFiliation = new ResponseFiliation();
                BeanUtils.copyProperties(list.get(i),responseFiliation);
                filiationList.add(responseFiliation);
            }
            Response response = new Response();
            BeanUtils.copyProperties(list.get(i),response);
            response.setApiProjectId(projectId);
            response.setSort(i);
            responseList.add(response);
        }
        responseParamMapper.addResponse(responseList);
        if(filiationList.size()==0){
           return 1;
        }
        return responseParamMapper.addResponseFiliation(filiationList);
    }

    @Override
    public int addNewLine(Response response) {
        String code = UUID.randomUUID().toString();
        response.setResponseCode(code);
        if(null != response.getParentResponseCode()){
            //添加层级关系
            ResponseFiliation responseFiliation = new ResponseFiliation();
            responseFiliation.setParentResponseCode(response.getParentResponseCode());
            responseFiliation.setResponseCode(code);
            responseParamMapper.addFiliation(responseFiliation);
        }
        return responseParamMapper.addNewLine(response);
    }

    @Override
    public int modifyResponse(Object value, String modifyField, Long responseId) throws Exception {

        Class<?> clazz=Class.forName("com.ruoyi.project.module.response.domain.Response");
        Response response=(Response) clazz.newInstance();
        response.setResponseId(responseId);
        if("ParamType".equalsIgnoreCase(modifyField)){
            clazz.getMethod("set"+modifyField,Integer.class).invoke(response,Integer.valueOf(value.toString()));
            return responseParamMapper.modifyResponse(response);
        }else if(value instanceof String){
            clazz.getMethod("set"+modifyField,String.class).invoke(response,value.toString());
        }

        return responseParamMapper.modifyResponse(response);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int delResponse(String responseCode) {
        responseParamMapper.delResponse(responseCode);
        responseParamMapper.delResponseFiliation(responseCode);
        return 1;
    }

    private List<ResponseParam> analysisParam(boolean ignorePageInfo,Object json, String parentKey, List<ResponseParam> list,String parentJsonKey){
        if(json instanceof JSONArray){
            ResponseParam param = new ResponseParam();
            param.setParamType(RESPONSE_VALUE_TYPE_ARRAY);
            JSONArray jsonArray = (JSONArray)json;
            int arrayI=0;
            for (Object aJsonArray : jsonArray) {
                ResponseParam paramTemp = new ResponseParam();
                String objKey = UUID.randomUUID().toString();
                paramTemp.setResponseCode(objKey);
                paramTemp.setParentResponseCode(parentKey);
                paramTemp.setParamName(""+arrayI);
                paramTemp.setParamDesc("数组元素["+(++arrayI)+"]");
                paramTemp.setParamType(RESPONSE_VALUE_TYPE_OBJECT);
                logger.debug("*******************aJsonArray={},value={}",aJsonArray.getClass(),aJsonArray.toString());
                list.add(paramTemp);
                if(aJsonArray instanceof JSON){
                    //如果为list,key名称为空
                    analysisParam(ignorePageInfo,aJsonArray, objKey, list,"");
                }else {
                    logger.debug("");
                    if(aJsonArray instanceof java.lang.Number){
                        paramTemp.setParamType(RESPONSE_VALUE_TYPE_NUMBER);
                        paramTemp.setParamMock(aJsonArray.toString());

                    }else if(aJsonArray instanceof java.lang.String){
                        paramTemp.setParamType(RESPONSE_VALUE_TYPE_STRING);
                        paramTemp.setParamMock(aJsonArray.toString());
                    }else{
                        paramTemp.setParamMock(aJsonArray.toString());
                    }
                }
            }
        }else if(json instanceof JSONObject){
            ((JSONObject) json).forEach((K,V)->{
//                logger.debug("parentJsonKey={},K={}",parentJsonKey,K);
//                "data".equals(parentJsonKey)&&
                if(!ignorePageInfo||
                        !("data".equals(parentJsonKey)&&StringUtils.inString(K,false,
                                "startRow","endRow","pageSize","pageNum","size","total","pages","prePage","nextPage","isFirstPage","isLastPage","hasPreviousPage","hasNextPage","navigatePages","navigatepageNums","navigateFirstPage","navigateLastPage","firstPage","lastPage"
                        ))
//                        (!"startRow".equals(K) && !"endRow".equals(K) && !"pageSize".equals(K) && !"pageNum".equals(K) && !"size".equals(K) && !"total".equals(K)
//                        && !"pages".equals(K) && !"prePage".equals(K) && !"nextPage".equals(K) && !"isFirstPage".equals(K) && !"isLastPage".equals(K)
//                        && !"hasPreviousPage".equals(K)  && !"hasNextPage".equals(K) && !"navigatePages".equals(K) && !"navigatepageNums".equals(K)
//                        && !"navigateFirstPage".equals(K) && !"navigateLastPage".equals(K)  && !"firstPage".equals(K) && !"lastPage".equals(K))
                ) {

                    ResponseParam param = new ResponseParam();
                    String objKey = UUID.randomUUID().toString();
                    param.setResponseCode(objKey);
                    param.setParamName(K);
                    param.setParamType(RESPONSE_VALUE_TYPE_OBJECT);

                    if(V!=null){
                        if(V instanceof java.lang.Number){
                            param.setParamType(RESPONSE_VALUE_TYPE_NUMBER);
                            param.setParamMock(V.toString());

                        }else if(V instanceof java.lang.String){
                           param.setParamType(RESPONSE_VALUE_TYPE_STRING);
                            param.setParamMock(V.toString());
                        }else if(V instanceof com.alibaba.fastjson.JSONArray){
                            param.setParamType(RESPONSE_VALUE_TYPE_ARRAY);
                        }
                        logger.debug("----------------------{}",V.getClass());
                    }
                    List<ResponseCompletion> responseCompletionList = responseParamMapper.completionParamName(K);
                    if(!responseCompletionList.isEmpty()){
                        String paramDesc = responseCompletionList.get(0).getParamDesc();
                        if(paramDesc!=null){
                            param.setParamDesc(paramDesc);
                        }
                    }
                    if(null != parentKey){
                        param.setParentResponseCode(parentKey);
                    }
                    list.add(param);
                    if (V instanceof JSONArray) {
                        analysisParam(ignorePageInfo,V,objKey,list,K);
                    }else if(V instanceof JSONObject){
                        analysisParam(ignorePageInfo,V,objKey,list,K);
                    }
                }
            });
        }
        return list;
    }

    @Override
    public int addFiliation(ResponseFiliation responseFiliation) {
        return responseParamMapper.addFiliation(responseFiliation);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int cleanResponse(Long projectId) {
        responseParamMapper.cleanResponseFiliation(projectId);
        return responseParamMapper.cleanResponse(projectId);
    }

}
